﻿using System;
using System.Collections.Generic;
using System.Data.Entity.Design;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using EntityFrameworkContrib.Design.VisualStudio.Properties;
using EnvDTE;

namespace EntityFrameworkContrib.Design.VisualStudio
{
	sealed class PluginManager
	{
		readonly Project project;

		public PluginManager( Project project )
		{
			this.project = project;
		}

		public void Broadcast( EntityClassGenerator generator )
		{
			Subscribers.ForEach( item => item.Subscribe( generator ) );
		}

		List<IEdmxCodeGeneratorSubscriber> Subscribers
		{
			get { return subscribers ?? ( subscribers = ResolveSubscribers() ); }
		}	List<IEdmxCodeGeneratorSubscriber> subscribers;

		List<IEdmxCodeGeneratorSubscriber> ResolveSubscribers()
		{
			List<IEdmxCodeGeneratorSubscriber> result = new List<IEdmxCodeGeneratorSubscriber>();
			foreach ( string file in System.IO.Directory.GetFiles( Directory, "*.dll" ) )
			{
                try
                {
                    AssemblyName assemblyName = AssemblyName.GetAssemblyName(file);
                    Assembly assembly = Assembly.Load( assemblyName );
					if ( assembly != null )
					{
			            EdmxCodeGeneratorSubscriberAttribute[] attributes = assembly.GetCustomAttributes( typeof(EdmxCodeGeneratorSubscriberAttribute), true ) as EdmxCodeGeneratorSubscriberAttribute[];
						if ( attributes != null && attributes.Length > 0 )
						{
							IEdmxCodeGeneratorSubscriber item = Activator.CreateInstance( attributes[0].SubscriberType ) as IEdmxCodeGeneratorSubscriber;
							if ( item != null )
							{
								Log( string.Format( "Found IEdmxCodeGeneratorSubscriber type '{0}'.", item.GetType().AssemblyQualifiedName ) );
								result.Add( item );
							}
						}
					}
                }
                catch ( Exception error )
                {
                	Log( string.Format( "An exception occured while processing the plugin directory: {0}.", error.Message ) );
                	Log( error.StackTrace );
                }
			}
			return result;
		}

		void Log( string message )
		{
			if ( project != null )
			{
              	LoggingHelper.LogOutputWindowPaneMessage( project, message );
			}
		}

		string Directory
		{
			get { return directory ?? ( directory = ResolvePluginDirectory() ); }
		}	string directory;

		static string ResolvePluginDirectory()
		{
			string result = Environment.ExpandEnvironmentVariables( Settings.Default.PluginDirectory );
			return !string.IsNullOrEmpty( result ) ? result : AppDomain.CurrentDomain.BaseDirectory;
		}
	}
}
